<?php
namespace app\services;

use app\utils\Functions as F;
use app\utils\Upload as Up;
use app\models\Creative;
use app\services\SolutionService;

class CreativeService extends BaseService {
    public $sspService = null;

    public $creativeBindSolutionMatrix = [
        'id' => 'id',
        'name' => 'name',
        'launch' => 'campaign',
        'status' => ['status', '$v==1 && $v=\Yii::t("creative", "waiting");
                                $v==2 && $v=\Yii::t("creative", "valid");
                                $v==3 && $v=\Yii::t("creative", "paused");
                                $v==4 && $v=\Yii::t("creative", "deleted");
                                $v==5 && $v=\Yii::t("creative", "expired");
                                $v==6 && $v=\Yii::t("creative", "closed");
                                $v==7 && $v=\Yii::t("creative", "unfinished");
                                $v==8 && $v=\Yii::t("creative", "unfinished");
                                $v==9 && $v=\Yii::t("creative", "unfinished");
                                return $v;'],
        'launchTime' => 'range',
        'modifiedDate' => 'last_update',
        'operate' => ['id', 'return "unbind";'],
    ];

    public $matrix = [
        'id'            => 'id',
        'name'          => 'name',
        'strategy'      => 'solution_name',
        'status'        => ['status', '$v==1 && $v="to-be-audit";
                                $v==2 && $v="passed";
                                $v==3 && $v="refused";
                                $v==4 && $v="paused";
                                $v==5 && $v="stoped";
                                $v==6 && $v="unfinished";
                                return $v;'],
        'creativeType'  => 'form',
        'materialType'  => ['format_id', '$v==1 && $v="static-pic";
                                          $v==2 && $v="dynamic-pic";
                                         $v==3 && $v="swf";
                                         $v==4 && $v="txt";
                                         $v==5 && $v="flv";
                                         $v==6 && $v="mp4";
                                         $v==7 && $v="ogg";
                                         $v==8 && $v="webm";
                                         return $v;'],
        'custom'        => 'is_custom',
        'cpeMaterialType' => 'cpe_ext',
        'creativeSize' => 'dim',
        'vocation' => 'vocation',
        'cost' => ['cost', 'return number_format($v, 2);'],
        'showCount' => 'shows',
        'clickCount' => 'clicks',
        'clickRate' => ['clickRate', 'return number_format($v, 2);'],
        'cpm' => ['cpm', 'return number_format($v, 2);'],
        'cpc' => ['cpc', 'return number_format($v, 2);'],
        'duration' => 'duration',
        'modifiedDate' => 'last_update',
        'operate' => 'edit, report, view',
    ];

    public function getAllCategories($adnwId) {
        $categories = $this->sort2LevelCates('CreativeCategory', 'name', 1);
        $sorted = [];
        foreach ($categories as $parent => $subs) {
            foreach ($subs as $sub) {
                $sorted[$parent][] = $sub['name'];
            }
        }
        return $this->toJson($sorted);
    }

    public function addMaterial($fileInfo, $solutionId, $advertiserId) {
        if (is_array($fileInfo)) {
            $material = $this->addNewMaterialRecord($solutionId, $advertiserId, $fileInfo);
            $fileInfo = $this->M('Material', $material['id']);
            $fileInfo['size'] = number_format($fileInfo['size']/1024, 2).'k';
        }
        return $fileInfo;
    }

    public function uploadPic($solutionId, $advertiserId, $ext = '') {
        $fileInfo = $this->upload();
        if (is_array($ext)) {
            if (!in_array(strtolower($fileInfo[0]['extension']), $ext)) {
                $this->NG($this->t('creative', 'Material format not correct!'));
            }
        }
        // upload done, return fileinfo
        return $this->addMaterial($fileInfo, $solutionId, $advertiserId);
    }

    public function uploadVideo($solutionId, $advertiserId) {
        $type = $_FILES['files']['type'][0];
        $pics = ['image/jpeg', 'image/png', 'image/jpg'];
        if (in_array($type, $pics)) {
            // return $this->uploadPic($solutionId, $advertiserId);
            return $this->NG($this->t('creative', 'Material format not correct!'));

        }
        $fileInfo = $this->upload(true);
        return $this->addMaterial($fileInfo, $solutionId, $advertiserId);
        //upload done, return fileinfo
    }

    /**
     * 获取上传文件的引用结果
     */
    public function getRef($result, $model) {
        if (is_array($result)) {
            $id = $result['id'];
            $user = $this->M('User', $result['upload_by']);
            $table = [
                'name' => $result['name'],
                'size' => $result['size'],
                'date' => $result['last_update'],
                'judgeInfo' => $this->auditPic($result, $model),
                'updater' => $user['name'],
            ];
            $preview = [
                'width' => $result['width'],
                'height' => $result['height'],
                'type' => $result['ext'],
                'address' => $this->getPicUrl($result['name']),
            ];
        }
        return ['id' => $id, 'table' => $table, 'preview' => $preview];
    }

    public function auditPic($attr, $model) {
        $adnetworkId = $this->S('ad_network_id');
        !$adnetworkId && $adnetworkId = 1;
        if($model == 'VideoAdspace' || $model == "MobileAdspace" || $model == "MobileVideoAdspace") {
            $auditResult = $this->t('creative', 'qualified');
        } else {
            $auditResult = $this->t('creative', 'unqualified');
            $sizes = $this->getAvailableCreativeSize($model, $adnetworkId, $this->I('soluton_id'));
            foreach ($sizes as $size) {
                if ($size['width'] == $attr['width']
                    && $size['height'] == $attr['height']) {
                    $auditResult = $this->t('creative', 'qualified');
                }
            }
        }
        return $auditResult;
    }

    public function getPicUrl($name) {
        $PIC = '/admath/materials/'.$name;
        return $this->getSiteBaseUrl().$PIC;
    }

    /**
     * 上传素材后写素材表
     */
    public function addNewMaterialRecord($solutionId, $advertiserId, $fileInfo) {
        foreach ($fileInfo as $info) {
            $data = $info;
            $data['advertiser_id'] = $advertiserId;
            $data['ext'] = strtolower($data['extension']);
            $data['name'] = $data['savename'];
            $data['path'] = $data['savepath'];
            // 获取 session user id
            $data['upload_by'] = $this->S('user_id');
            $data['upload_ip'] = F::get_client_ip();
            return $this->save('Material', $data);
        }
    }

    public function getPicture($name) {
        $savePath = \Yii::$app->params['upload']['savePath'];
        $name = $savePath.$name;
        if (!file_exists($name)) {
            header("Content-type: image/png");
            echo file_get_contents($savePath.'404.png');
        }
        $size = getimagesize($name);
        $fp = fopen($name, 'rb');
        if ($size && $fp) {
            header("Content-type: {$size['mime']}");
            fpassthru($fp);
        }
        exit;
    }

    public function getConditionAdspaceIds($solutionId) {
        //使用了广告位白名单 
        $adspaceWhere = [];
        $adspaceWhere['solution_id'] = $solutionId;
        $adspaceWhere['is_whitelist'] = 1;
        $adspaceWhere['status'] = 1;
        $conditionAdspace = $this->getAll('ConditionAdspace', $adspaceWhere);
        $adIds = $this->arrayGroup($conditionAdspace, 'adspace_id', ['adspace_id']);
        $adIds = array_keys($adIds);
        return $adIds;
    }

    public function getAdspaces($model, array $ids, $ad_network_id='') {
        if (empty($ids)) return [];
        !$ad_network_id && $ad_network_id = 1;
        $where = 'ad_network_id = '.$ad_network_id.' and id in ('.implode(',', $ids).')';
        $adspaces = $this->getAll('Adspace', $where);
        return $adspaces;
    }

    public function getTargetedAdspace($adspaceIds, $type='no_limit')
    {
        if ($type == 'black') {
            $on = 'status = 1';
            $allIds = $this->getAll('ResourceAppAdspaceMap', $on);
            $allIds = array_column($allIds, 'adspace_id');
            $adspaceIds = array_diff($allIds, $adspaceIds);
        }
        return $adspaceIds;
    }

    public function getTargetedAdspaceFormats($adspaceIds, $type='no_limit')
    {
        $adspaceIds = $this->getTargetedAdspace($adspaceIds, $type);
        if (!$adspaceIds) {
            $adspaceIds = $this->getAll('ResourceAppAdspaceMap', ['status' => 1]);
            $adspaceIds = array_column($adspaceIds, 'adspace_id');
        }
        $formats = $this->getAll('MobileAdspace', ['id' => $adspaceIds]);
        $formats = array_column($formats, 'format_list');
        $formats = implode(',', $formats);
        $formats = explode(',', $formats);
        $formats = array_unique($formats);
        return $formats;
    }

    public function getTargetedAppAllowedSizes($adspaceIds, $type='no_limit')
    {
        $ret = [];
        $adspaceIds = $this->getTargetedAdspace($adspaceIds, $type);
        if (!$adspaceIds) {
            $adspaceIds = $this->getAll('ResourceAppAdspaceMap', ['status' => 1]);
            $adspaceIds = array_column($adspaceIds, 'adspace_id');
        }
        if ($adspaceIds) {
            $on = ['id' => $adspaceIds];
            $ads = $this->getAll('MobileAdspace', $on);
            $sizes = array_column($ads, 'ext_size');
            $sizes = implode(',', $sizes);
            $sizes = explode(',', $sizes);
            $sizes = array_unique($sizes);
            foreach ($sizes as $size) {
                list ($width, $height) = explode('*', $size);
                $ret[] = ['width' => $width, 'height' => $height];
            }
        }
        return $ret;
    }

    public function getAppAvailableCreativeSize($solutionId)
    {
        !$solutionId && $solutionId = $this->s('solution_id');
        $service = new SolutionService();
        $bwList = $service->getConditionBWList($solutionId, 'is_for_mobile');
        $conditions = $service->getConditionsKey($solutionId, 'is_for_mobile');
        $type = 'no_limit';
        if (isset($bwList['ConditionAdspace'])) {
            $type = $bwList['ConditionAdspace'];
        }
        $ads = [];
        if (isset($conditions['ConditionAdspace'])) {
            $ads = $conditions['ConditionAdspace'];
        }
        $sizes = $this->getTargetedAppAllowedSizes($ads, $type);
        return $sizes;
    }

    /**
     * 根据adnetwork所指定的网络查找该网络的所有广告位尺寸集合
     * 若solution定义了广告位白名单定向，则创意可选尺寸仅为所
     * 定义的白名单广告位尺寸集合, 否则为尺寸全集
     */
    public function getAvailableCreativeSize($model, $adnetworkId='', $solutionId='', $type='') {
        if ($type == 'mobile' || strtolower($model) == 'mobileadspace') {
            return $this->getAppAvailableCreativeSize($solutionId);
        }
        $adspaces = [];
        $where = [];
        if (strtolower($model) == 'videoadspace' && $type) {
            $where[] = "ad_form=$type";
        }
        if ($adnetworkId) {
            $where[] = "ad_network_id=$adnetworkId";
        }
        if (strtolower($model) == 'mobileadspace' && $type) {
            $type == 'web' && $where[] = "type = 1";
            $type == 'app' && $where[] = "type <> 1";
        }
        if(strtolower($model) == 'adspace' && $type == 'cpe-banner'){
            $where[] = "cpe_support=1";
        }
        if (!in_array(0, $this->s('media_slot'))) {
            $ids = implode(',', $this->s('media_slot'));   
            $medias = $this->getAll('AdnetworkMedia', "id in ($ids)");
            $medias = array_column($medias, 'media_id');
            $mediaIds = array_values($medias);
            if ($mediaIds) {
                $adspaceMediaIds = implode(',', $mediaIds);
                $where[] = " media_id in ($adspaceMediaIds) ";
            }
        }
        $where = implode(' and ', $where);
        $adspaces = $this->getAll($model, $where);
        $sizeMap = [];
        $sizes = [];
        if (strtolower($model) != 'mobileadspace') {
            foreach ($adspaces as $adspace) {
                if ($adspace['width'] == 0) continue;
                $sMap = $adspace['width'].'*'.$adspace['height'];
                if (in_array($sMap, $sizeMap)) {
                    continue;
                }
                $sizeMap[] = $sMap;
                $sizes[] = ['width' => $adspace['width'], 
                    'height'=> $adspace['height']];
            }
        } else {
             foreach ($adspaces as $adspace) {
                if (!$adspace['ext_size']) continue;
                $adspaceSizes = explode(',', $adspace['ext_size']);
                foreach ($adspaceSizes as $adSize) {
                    $sMap = $adSize;
                    if (in_array($sMap, $sizeMap)) {
                        continue;
                    }
                    $sizeMap[] = $sMap;
                    $sMap = explode('*', $sMap);
                    $sizes[] = ['width' => $sMap[0], 
                        'height'=> $sMap[1]];
                }
            }           
        }
        return $sizes;
    }

    public function checkOverlayMaterail() {
        //size
        $adnetworkId = $this->S('ad_network_id');
        $sizes = $this->getAvailableCreativeSize('VideoAdspace', $adnetworkId, $this->I('solution_id'), 'overlay');
        $sizeSet = [];
        foreach ($sizes as $size) {
            $sizeSet[] = implode('_', array_values($size));
        }
        $fileInfo = $this->upload(true);
        $file = $fileInfo[0];
        if (!in_array($file['width'].'_'.$file['height'], $sizeSet)) {
            return false;
        }
        //format
        if (!in_array($file['extension'], ['jpg', 'jpeg', 'swf'])) {
            return false;
        }
        return $fileInfo;
    }

    public function getCreativeFormAllowed() {
        $forms = $this->S('traffic_slot');
        foreach ($forms as &$form) {
            $form -= 1;
        }
        $forms = implode(',', $forms);
        return $forms;
    }

    public function getCreativesBySolutionId($solutionId) {
        $aIds = $this->getAIds();
        if (!$aIds) return [];
        $where = " advertiser_id in $aIds ";
        if (!$solutionId) {
            $forms = $this->getCreativeFormAllowed();
            $where .= " and form in ($forms) and status <> 5";
            return $this->getAll('Creative', $where);
        }
        $where .= " and solution_id=$solutionId ";
        $where .= " and status = 1 ";
        $maps = $this->getAll('SolutionCreativeMap', $where);
        if (!$maps || count($maps) == 0) return [];
        $maps = $this->arrayGroup($maps, 'solution_id', ['creative_id']);
        $creativeIds = implode(',', array_values(array_shift($maps)));
        return Creative::find()->where("id in ($creativeIds)")->asArray()->indexBy('id')->all();
    }

    public function getCreativesList($solutionId='') {
        $aIds = $this->getAdvertiserIdArr();
        if (!$aIds) return [];
        $where = ['advertiser_id' => $aIds];
        $creativeWhere = $where;
        if (!$solutionId) $solutionId = $this->I('solution_id');
        if ($solutionId) {
            $where['id'] = $solutionId;
            $creativeWhere['solution_id'] = $solutionId;
        }
        $solutions = $this->getAll('Solution', $where);
        $crts = $this->getCreativesBySolutionId($solutionId);
        $report = new ReportService();
        $creativeReportData = $report->getCreativeReportData();
        $solutionCreativeMap = $this->getAll('SolutionCreativeMap', ['status' => 1]);
        $solutionCreativeMap = $this->arrayGroup($solutionCreativeMap, 'creative_id', ['solution_name']);

        foreach ($crts as $k => &$crt) {
            $crt['form'] = $this->getCreativeType($crt);
            $crt['solution_name'] = '';
            if (isset($solutionCreativeMap[$crt['id']])) {
                $crt['solution_name'] = implode(',', $solutionCreativeMap[$crt['id']]);
            }
            $crt['vocation'][] = $this->getCategorieById($crt['category_id']);
            $crt['dim'] = $crt['width'].'*'.$crt['height'];
            if($crt['form'] == 'cpe'){
                $cpe_size_list = explode(',', $crt['cpe_size_list']);
                $crt['dim'].= ','.$cpe_size_list[0];
            }
            $creativeReport = ['cost' => 0.00,
                'shows' => 0,
                'clicks' => 0,
                'clickRate' => 0.00,
                'cpm' => 0.00,
                'cpc' => 0.00];
            if (in_array($crt['id'], array_keys($creativeReportData))) 
            {
                $creativeReport = $creativeReportData[$crt['id']];
            }
            $crt = array_merge($crt, $creativeReport);
            if (in_array($this->S('user_rank'), ['agent', 'advertiser'])) {
                $creativeReport['shows'] = 0;
                $creativeReport['clicks'] = 0;
                $creativeReport['clickRate'] = 0.00;
                $creativeReport['cpm'] = 0.00;
                $creativeReport['cpc'] = 0.00;
            }
        }
        return $this->fieldsMap($this->matrix, $crts);
    }

    public function getCreativeType($creative) {
        $form = 'banner';
        switch ($creative['form']) {
            case 0:
                $form = 'banner';
                break;
            case 1:
                $form = 'video';
                break;
            case 2:
                $creative['type'] == 5 && $form = 'mobile-web';
                $creative['type'] == 6 && $form = 'mobile-app';
                break;
            case 3:
                $form = 'mobile-video';
                break;
            case 4:
                $form = 'cpe';
                break;
            default:
                break;
        }
        return $form;
    }

    public function getSolutionUnbindCreative($solutionId) {
        $solution = $this->getOne('Solution', ['id' =>  $solutionId]);
        $where = [];
        $where['solution_id'] = $solutionId;
        $where['status'] = 1;
        $advertiserId = $solution['advertiser_id'];
        $where['advertiser_id'] = $advertiserId;
        $bindCreatives = $this->getAll('SolutionCreativeMap', $where);
        $bindCreatives = $this->arrayGroup($bindCreatives, 'creative_id', ['creative_id']);
        $bindCreativeIds = array_keys($bindCreatives);
        $crtWhere = " advertiser_id = $advertiserId ";
        $type = $solution['type'];
        $trafficSlot = $this->S('traffic_slot');
        foreach ($trafficSlot as &$ttype) {
            $ttype -= 1;
        }
        if ($type == 2) {
            $formIds = array_intersect([2,3], $trafficSlot);
        } else {
            $formIds = array_intersect([0,1], $trafficSlot);
        }
        if(in_array('1',$trafficSlot)){
            array_push($formIds,'4');
        }
        $formIds = implode(',', $formIds);
        $crtWhere .= " and form in ($formIds) ";
        if (count($bindCreativeIds)) {
            $ids = implode(',', $bindCreativeIds);
            $crtWhere .= " and id not in ($ids) ";
        }
        $crtWhere .= " and status=1 ";
        $creatives = $this->getAll('Creative', $crtWhere);
        $unbindCreatives = [];
        foreach ($creatives as $creative) {
            $crtId = $creative['id'];
            if (in_array($crtId, $bindCreativeIds)) {
                continue;
            }
            $creative['form'] = $this->getCreativeType($creative);
            $creative['solution_name'] = '';
            $creative['vocation'][] = $this->getCategorieById($creative['category_id']);
            $creative['dim'] = $creative['width'].'*'.$creative['height'];
            if($creative['form'] == 'cpe'){
                $cpe_size_list = explode(',', $creative['cpe_size_list']);
                $creative['dim'].= ','.$cpe_size_list[0];
            }
            $creativeReport = ['cost'       => 0.00,
                               'shows'      => 0,
                               'clicks'     => 0,
                               'clickRate'  => 0.00,
                               'cpm'        => 0.00,
                               'cpc'        => 0.00];
            $unbindCreatives[$crtId] = array_merge($creative, $creativeReport);
        }
        return $this->fieldsMap($this->matrix, $unbindCreatives);
    }

    public function saveNewSolutionCreativeMap($solution, $creative) {
        if (is_numeric($creative)) {
            $creative = $this->M('Creative', $creative);
        }
        if (is_numeric($solution)) {
            $solution = $this->M('Solution', $solution);
        }
        $map = [];
        $map['solution_id'] = $solution['id'];
        $map['solution_name'] = $solution['name'];
        $map['creative_id'] = $creative['id'];
        $map['creative_name'] = $creative['name'];
        $map['ad_network_id'] = $solution['ad_network_id'];
        $map['advertiser_id'] = $solution['advertiser_id'];
        return $this->save('SolutionCreativeMap', $map);
    }

    public function getCategoryNameById($categoryId) {
        $vocation = $this->getCategorieById($categoryId);
        $category = $vocation['tags'];
        $categories = explode(', ', $category);
        $parent = array_shift($categories);
        $child = $this->t('creative', 'All');
        if (count($categories)) {
            $child = array_shift($categories);
        }
        return [$parent, $child];
    }

    public function getCategorieById($categoryId) {
        $where = ['category_id' => $categoryId];
        $cates = $this->getAll('CreativeCategory', $where);
        $cate = array_pop($cates);
        $ad_network = $this->M('AdNetwork', $cate['ad_network_id']);
        $vocation = ['channel' => $ad_network['name']];
        if ($cate['parent_category_id'] == 0) {
            $vocation['tags'] = $cate['name'];
        } else {
            $pcates = $this->getAll('CreativeCategory', ['category_id' => $cate['parent_category_id']]);
            $pcate = array_pop($pcates);
            $vocation['tags'] = $pcate['name'].', '.$cate['name'];
        }
        return $vocation;
    }

    public function getMaterialFormat($ext) {
        switch ($ext) {
            //static-pic
        case 'png':
        case 'jpg':
        case 'jpeg':
            $formatId = 1;
            break;
            //dynamic pic
            case 'gif':
                $formatId = 2;
                break;
            case 'swf':
                $formatId = 3;
                break;
            case 'txt':
                $formatId = 4;
                break;
            case 'flv':
                $formatId = 5;
                break;
            case 'mp4':
                $formatId = 6;
                break;
            case 'ogg':
            case 'ogv':
                $formatId = 7;
                break;
            case 'webm':
                $formatId = 8;
                break;
            default:
                $formatId = 4;
                break;
        }
        return $formatId;
    }

    /**
     * 根据传递的创意父子分类名获取分类自增id
     */
    public function getCreativeCategoryId($parent, $child) {
        $child == '全部小类' && $child = '';
        $child == 'All' && $child = '';
        $sql = "select c.id, c.category_id cid, 
            p.name pname, c.name cname,
            c.parent_category_id pcid,
            p.id pid
            from {{%creative_category}} as c
            inner join {{%creative_category}} as p
            on c.parent_category_id = p.category_id
            where p.name = '$parent'";
        if ($child) $sql .= " and c.name = '$child'";
        $conn = \Yii::$app->db;
        $cmd = $conn->createCommand($sql);
        $cate = $cmd->queryOne();
        if (!$child) return $cate['pcid'];
        return $cate['cid'];
    }

    /**
     * get ad_network_id by creative(creativeId)
     */
    public function getCreativeAdNetworkId($creative) {
        if (is_int($creative)) {
            $creative = $this->M('Creative', $creativeId);
        }
        if (!isset($ad_network_id)) {
            $ad_network_id = $this->S('ad_network_id');
        }
        !$ad_network_id && $ad_network_id = 1;
        return $ad_network_id;
    }

    public function getSspCreativeCode($creativeId) {
        $where = ['creative_id' => $creativeId];
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        if (!is_array($sspCreatives)) {
            return $this->t('creative', 'Creative not found!');
        }
        $sspCreative = array_shift($sspCreatives);
        return $sspCreative['creative_code'];
    }

    /**
     * creative 对应在 ssp 上的信息
     */
    public function saveCreativeSsp($creative, $isUpdate=false) {
        $sspCreative['creative_id'] = $creative['id']; 
        $sspCreative['ad_network_id'] = 1;
        //唯一键
        $uniqueKey = $sspCreative;
        $sspCreative['category_id'] = (string) $creative['category_id'];
        $sspCreative['form'] = $creative['form'];
        if ($creative['form'] == 0 || ($creative['form'] == 2 && $creative['type'] == 5)) {
            $sspCreative['creative_code'] = $this->replaceCreativeCodeMacros($creative);
        } else {
            $sspCreative['creative_code'] = '';
        }

        $isExist = \app\models\CreativeSsp::find()->where($uniqueKey)->one();
        $sspCreative['status'] = 0;
        //若已经上传 
        if ($isUpdate && $isExist) {
            // 已上传和待更新的状态设置为待更新
            if (in_array($isExist['status'], [1, -2])) {
                $sspCreative['status'] = -2;
                $sspCreative['ssp_audit_status'] = 0;
            }
        }
        $save = $this->saveOn('CreativeSsp', $uniqueKey, $sspCreative);
        return $save;
    }

    /**
     * 替换广告位模板中的宏
     */
    public function replaceCreativeCodeMacros($creative) 
    {
        $template = $this->M('CreativeTemplate', $creative['template_id']);
        $code = $template['code']; 
        $macros = $this->getMacroReplacement();
        foreach ($macros as $macro => $attr) {
            if ($attr && isset($creative[$attr])) {
                $value = $creative[$attr];
                if ($attr == 'landing_page') {
                    $value = urlencode($value);
                }
                //若用户未提供曝光监测url则替换为空
                $code = str_replace($macro, $value, $code);
            }
        }
        $cdn = $macros['{!dsp_cdn_url}'];
        $code = str_replace('{!dsp_cdn_url}', $cdn, $code);
        return $code;
    }

    public function getCreativeMaterialUrl($materialId) {
        $material = $this->M('Material', (int)$materialId);  
        $name = $material['name'];
        $cdn = \Yii::$app->params['cdn'];
        $url = $cdn.$name;
        return $url;
    }

    public function getMacroReplacement($ad_network_id=1) {
        $macros = [
            //    'dsp_click_url' => 'click_monitor_url',
            //'{!dsp_show_url}' => 'show_monitor_url',
            '{!dsp_creative_id}'        => 'id',
            '{!dsp_creative_type}'      => 'format_id',
            '{!dsp_creative_width}'     => 'width',
            '{!dsp_creative_height}'    => 'height',
            '{!dsp_creative_monitor}'   => 'click_monitor_url',
            '{!dsp_creative_landingpage}'   => 'landing_page',
            '{!dsp_creative_impr}'      => 'show_monitor_url',
            '{!dsp_creative_material}'  => 'file_url',
            '{!dsp_creative_code}'      => 'custom_code',
            //'dsp_cdn_url' => 'dsp_cdn_url',
        ];
        $ssp = $this->M('AdNetwork', $ad_network_id);
        if (!$ad_network_id) {
            $ssp = array_shift($ssp);
        }
        if (!$ssp || empty($ssp)) {
            $ssp['name'] = 'vamaker';
        }
        $configMacros = \Yii::$app->params['ssp'][$ssp['name']]['macros']; 
        $macros = array_merge($macros, $configMacros);
        return $macros;
    }

    /**
     * 上传创意到 ssp
     * if creative id specified, upload the corresponding 
     * creative only, otherwise try upload all creatives
     */
    public function uploadCreative($creativeId='') {
        if (!$creativeId) {
            $where = ['status' => 0];
        } else {
            $where = ['creative_id' => $creativeId];
        }
        $where['ad_network_id'] = 1;
        $where['form'] = 0;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'upload', 'banner');

        $where['form'] = 1;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'upload', 'video');

        $where['form'] = 2;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'upload', 'mobile');

        $where['form'] = 3;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'upload', 'mobile_video');

        $where['form'] = 4;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'upload', 'cpe');
    }

    /**
     * update creative to ssp
     * if creative id specified, update the corresponding 
     * creative only, otherwise try update all creatives
     */
    public function updateCreative($creativeId='') {
        $where = ['status' => -2];
        if ($creativeId) {
            $where['creative_id'] = $creativeId;
        }
        $where['ad_network_id'] = 1;
        $where['form'] = 0;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'update', 'banner');

        $where['form'] = 1;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'update', 'video');

        $where['form'] = 2;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'update', 'mobile');

        $where['form'] = 3;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'update', 'mobile_video');

        $where['form'] = 4;
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        $this->sendCreativesToSsp($sspCreatives, 'update', 'cpe');
    }

    /**
     * send creative to ssp
     */
    public function sendCreativesToSsp($sspCreatives, $action, $type) {
        foreach ($sspCreatives as $sspCreative) {
            $creativeId = $sspCreative['creative_id'];
            $creative = $this->M('Creative', $creativeId); 
            $ad_network_id = $sspCreative['ad_network_id'];
            if (!$ad_network_id) continue;
            $ssp = $this->M('AdNetwork', $ad_network_id);
            $sspService = new SspService($ssp['name']);
            $apiType = $type;
            $form = 0;
            if ($type == 'video' || $type == 'mobile_video') {
                $type == 'video' && $form = '1';
                $type == 'mobile_video' && $form = '3';
                $uploadData = $this->packVideoCreative($creative, $ad_network_id, $form);
            } else if ($type == 'mobile') {
                if ($creative['type'] == 5) {
                    $apiType = 'web';
                    $uploadData = $this->packMobileWebCreative($creative, $ad_network_id);
                } else if ($creative['type'] == 6) {
                    $apiType = 'app';
                    $uploadData = $this->packMobileAppCreative($creative, $ad_network_id);
                }
            } else if ($type == 'cpe') {
                $uploadData = $this->packCpeCreative($creative, $ad_network_id);
            } else {
                $uploadData = $this->packCreative($creative, $ad_network_id);
            }
            $response = $sspService->sendCreative($uploadData, $action, $apiType);
            // upload/update successfully
            if ($response == '""') {
                $this->updateSspCreative($creativeId, $ad_network_id, $action);
            }
        }
    }

    /**
     * syncronize ssp audit status
     * all vamaker only
     */
    public function updateCreativeAuditStatus($creativeId=0) {
        $where[] = "status = 1";
        if($creativeId) {
            $where[] = "creative_id = $creativeId";
        } else {
            $time = date('Y-m-d 00:00:00', strtotime('-2 day'));
            $where[] = "last_update>='$time'";
        }
        $where[] = "ad_network_id = 1";
        $where = implode(' and ', $where);
        $sspCreatives = $this->getAll('CreativeSsp', $where);
        foreach ($sspCreatives as $sspCreative) {
            $ad_network_id = $sspCreative['ad_network_id'];
            $query = '?id='.$sspCreative['creative_id'];
            $ssp = $this->M('AdNetwork', $ad_network_id);
            $sspService = new SspService($ssp['name']);
            $sspCreative['form'] == 0 && $apiType = 'banner';
            $sspCreative['form'] == 1 && $apiType = 'video';
            $sspCreative['form'] == 2 && $apiType = 'web';
            $sspCreative['form'] == 3 && $apiType = 'mobile_video';
            $sspCreative['form'] == 4 && $apiType = 'banner';
            $response = $sspService->getCreative($query, 'status', $apiType);   
            $status = json_decode($response, true);
            $auditStatus = ['status' => $sspCreative['status'], 
                            'ssp_audit_status'=>$status['status']];
            $status['status'] >= 1000 && $auditStatus = ['status' => $sspCreative['status'], 
                                            'ssp_audit_status'=> -1];
            $this->updateSspCreative($status['id'], $ad_network_id, 'status', $auditStatus);
        }
    }

    /**
     * pack creative for upload/update
     */
    public function packCreative($creative, $ad_network_id) {
        // 打包成对应 ssp 所需的格式
        $sspOn = ['creative_id' => $creative['id'],
                  'ad_network_id' => $ad_network_id];
        $sspCreatives = $this->getAll('CreativeSsp', $sspOn);
        $sspCreative = array_pop($sspCreatives);
        $domain = $creative['adomain_list'];
        if (!$domain) $domain = $creative['landing_page'];
        $domain = $this->getAdomain($domain);
        $pack = [
            'id'            => $sspCreative['creative_id'],
            'width'         => $creative['width'],
            'height'        => $creative['height'],
            'format'        => $creative['format_id'],
            'category'      => $creative['category_id'],
            'html_snippet'  => $sspCreative['creative_code'],
            'adomain_list'  => explode(';', $domain),
            'custom'        => $creative['is_custom'],
        ];
        return json_encode($pack, JSON_UNESCAPED_UNICODE);
    }

    /**
     * pack creative for upload/update
     */
    public function packCpeCreative($creative, $ad_network_id, $form=4) {
        // 打包成对应 ssp 所需的格式
        $sspOn = ['creative_id'   => $creative['id'],
                  'form'          => $form,
                  'ad_network_id' => $ad_network_id];
        $sspCreatives = $this->getAll('CreativeSsp', $sspOn);
        $sspCreative = array_pop($sspCreatives);

        $domain = $creative['adomain_list'];
        if (!$domain) $domain = $creative['landing_page'];
        $domain = $this->getAdomain($domain);

        $pack = [
            'id'                    => $sspCreative['creative_id'],
            'width'                 => $creative['width'],
            'height'                => $creative['height'],
            'format'                => $creative['format_id'],
            'category'              => $creative['category_id'],
            'pic_url'               => $creative['file_url'],
            'adomain_list'          => explode(';', $domain),
            'landingpage'           => '{!vam_click_url}{!dsp_click_url}'.$creative['cpe_landing_page'],
            'show_monitor_urls'     => explode(';;;', $creative['cpe_show_monitor_url']),
        ];
        $objs = ['file_url' => 'cpe_file_url', 
                 'duration' => 'cpe_duration',
                 'width'    => 'cpe_size_list', 
                 'height'   => 'cpe_size_list', 
                 'format'   => 'cpe_format_id'];
        $cpeInfo = [];
        foreach ($objs as $key => $obj) {
            if (isset($creative[$obj])) {
                $fields = explode(',', $creative[$obj]);
                foreach ($fields as $k => $val) {
                    if ($key == 'width') $val = strstr($val, '*', true);
                    if ($key == 'height') $val = trim(strstr($val, '*'), '*');
                    is_int($val) && $val = (int) $val;
                    is_float($val) && $val = (float) $val;
                    $cpeInfo[$k][$key] = $val;
                }
            }
        }
        $pack['cpe_info'] = $cpeInfo;
        return json_encode($pack, JSON_UNESCAPED_UNICODE);
    }

    public function packVideoCreative($creative, $ad_network_id, $form=1) {
        // 打包成对应 ssp 所需的格式
        $sspOn = ['creative_id'     => $creative['id'],
                  'ad_network_id'   => $ad_network_id,
                  'form'            => $form];
        $sspCreatives = $this->getAll('CreativeSsp', $sspOn);
        $sspCreative = array_pop($sspCreatives);

        $cdn = \yii::$app->params['cdn'];
        $pack = [
            'id'            => $sspCreative['creative_id'],
            'advertiser'    => $creative['advertiser_name'],
            'width'         => $creative['width'],
            'height'        => $creative['height'],
            'format'        => $creative['format_id'],
            'creative_type' => $creative['type'],
            'category'      => $creative['category_id'],
            'duration'      => $creative['duration'],
            'fileurl'       =>  $creative['file_url'],
            'landingpage'   => '{!vam_click_url}{!dsp_click_url}'.urlencode($creative['landing_page']),
            'adomain_list'  => explode(';', $creative['adomain_list']),
            'custom'        => $creative['is_custom'],
        ];
        if ($creative['pic_url']) {
            $pack['pic_url'] = $creative['pic_url'];
        }
        if ($creative['title']) {
            $pack['title'] = $creative['title'];
        }
        if ($form == 3) {
            //mob video
            $pack['adtype'] = 1;
            //mob video native
            if ($creative['ad_type'] == 3) {
                $pack['adtype'] = 2;
            }
        }
        if ($form == 1 && $creative['click_monitor_url'])
            $pack['landingpage'] = $creative['landing_page'];
        return json_encode($pack, JSON_UNESCAPED_UNICODE);
    }

    private function shift($data, $seperator=',') {
        $datas = explode($seperator, $data);
        return array_shift($datas);
    }

    public function packCornerCreative($creative, $ad_network_id) {
        // 打包成对应 ssp 所需的格式
        $sspOn = ['creative_id' => $creative['id'], 'ad_network_id' => $ad_network_id];
        $sspCreatives = $this->getAll('CreativeSsp', $sspOn);
        $sspCreative = array_pop($sspCreatives);

        $cdn = \yii::$app->params['cdn'];
        $pack = [
            'id'            => $sspCreative['creative_id'],
            'advertiser'    => $creative['advertiser_name'],
            'width'         => $this->shift($creative['width']),
            'height'        => $this->shift($creative['height']),
            'format'        => $this->shift($creative['format_id']),
            'fileurl'       => $creative['file_url'],
            'category'      => $creative['category_id'],
            'duration'      => $creative['duration'],
            'landingpage'   => '{!vam_click_url}{!dsp_click_url}'.urlencode($creative['landing_page']),
            'adomain_list'  => explode(';', $creative['adomain_list']),
            'custom'        => $creative['is_custom'],
        ];
        return json_encode($pack, JSON_UNESCAPED_UNICODE);
    }

    public function packMobileWebCreative($creative, $ad_network_id) {
        // 打包成对应 ssp 所需的格式
        $sspOn = ['creative_id' => $creative['id'],
                  'ad_network_id' => $ad_network_id];
        $sspCreatives = $this->getAll('CreativeSsp', $sspOn);
        $sspCreative = array_pop($sspCreatives);

        $domain = $creative['adomain_list'];
        if (!$domain) $domain = $creative['landing_page'];
        $domain = $this->getAdomain($domain);

        $pack = [
            'id'            => $sspCreative['creative_id'],
            'width'         => $creative['width'],
            'height'        => $creative['height'],
            'format'        => $creative['format_id'],
            'category'      => $creative['category_id'],
            'html_snippet'  => $sspCreative['creative_code'],
            'adomain_list'  => explode(';', $domain),
            'custom'        => $creative['is_custom'],
        ];
        return json_encode($pack, JSON_UNESCAPED_UNICODE);
    }

    public function packMobileAppCreative($creative, $ad_network_id) {
        // 打包成对应 ssp 所需的格式
        $sspOn = ['creative_id' => $creative['id'],
                  'ad_network_id' => $ad_network_id];
        $sspCreatives = $this->getAll('CreativeSsp', $sspOn);
        $sspCreative = array_pop($sspCreatives);

        $domain = $creative['adomain_list'];
        if (!$domain) $domain = $creative['landing_page'];
        $domain = $this->getAdomain($domain);

        $pack = [
            'id'            => $sspCreative['creative_id'],
            'width'         => explode(',', $creative['width'])[0],
            'height'        => explode(',', $creative['height'])[0],
            'advertiser'    => $creative['advertiser_name'],
            'format'        => $creative['format_id'],
            'category'      => $creative['category_id'],
            'adomain_list'  => explode(';', $domain),
            'landingpage'   => '{!vam_click_url}{!dsp_click_url}'.urlencode($creative['landing_page']),
            'pic_urls'      => explode(',', $creative['file_url']),
            'adtype'        => $creative['ad_type'] + 1,
            'title'         => $creative['title'],
            'text'          => $creative['txt'],
            'hero_app'      => $creative['hero_app'],
            'custom'        => $creative['is_custom'],
            'subadtype'     => $creative['subadtype'],
        ];
        return json_encode($pack, JSON_UNESCAPED_UNICODE);
    }

    /**
     * update status after upload/update creative to ssp
     */
    public function updateSspCreative($creative_id, $ad_network_id, $action='upload', $auditStatus=[]) 
    {
        switch ($action) {
        case 'upload':
            $status = 1;
            $ssp_audit_status = 0;
            break;
        case 'update':
            // 已经更新和已经上传无差别
            $status = 1;
            $ssp_audit_status = 0;
            break;
        case 'status':
            if (!empty($auditStatus)) {
                $status = $auditStatus['status'];
                $ssp_audit_status = $auditStatus['ssp_audit_status'];
            }
            break;
        default:
            $status = 1;
            $ssp_audit_status = 0;
            break;
        }
        $uniqueOn = [
            'creative_id' => $creative_id,
            'ad_network_id' => $ad_network_id,
        ];
        //$update = $uniqueOn;
        $update['status'] = $status;
        $update['ssp_audit_status'] = $ssp_audit_status;
        $this->saveOn('CreativeSsp', $uniqueOn, $update);
        // update solution status
        // once creative uploaded, the corresponding solution shold be set as ready for launch status
        // creative 状态与 solution 状态无关，solution 一经建立完成（出价完成）便处于可投放状态；
        // 没有creative 的solution不会被打入 package
        /*
        if ($ssp_audit_status != 3) {
            $creative = $this->M('Creative', $creative_id);
            $solutionId = $creative['solution_id'];
            $this->saveOn('Solution', ['id' => $solutionId], ['status' => 2]);
        }
         */
    }

    public function changeStatusToId($status) {
        switch ($status) {
        case 'pause':
            $statusId = 4;
            break;
        case 'resume':
            $statusId = 1;
            break;
        default:
            $statusId = 1;
            break;
        }
        return $statusId;
    }

    public function getCreativeBindSolutions($creativeId) {
        $creative = $this->M('Creative', $creativeId);
        $mapWhere = [];
        //$mapWhere['advertiser_id'] = $creative['advertiser_id'];
        $mapWhere['creative_id'] = $creative['id'];
        $mapWhere['status'] = 1;
        $maps = $this->getAll('SolutionCreativeMap', $mapWhere);
        $solutionIds = $this->arrayGroup($maps, 'solution_id', ['solution_id']);
        $solutionIds = array_keys($solutionIds);
        $solutions = [];
        if (count($solutionIds)) {
            $where = "id in (".implode(',', $solutionIds).")";
            $solutions = $this->getAll('Solution', $where);
        }

        foreach ($solutions as &$solution) {
            $solution['range'] = $solution['start_date'].' - '.$solution['end_date'];
            $campaign = $this->M('Campaign', $solution['campaign_id']);
            $solution['campaign'] = $campaign['name'];
        }
        return $this->fieldsMap($this->creativeBindSolutionMatrix, $solutions);
    }

    public function updateCreativeStatus($creativeId, $type) {
        if ($type == 'unlink') {
            $service = new SolutionService();
            $solutionId = $this->I('solution_id'); 
            return $service->unbindCreative($solutionId, $creativeId);
        }
        $statusId = $this->changeStatusToId($type);
        return $this->saveOn('Creative', ['id' => $creativeId], ['status' => $statusId]);
    }

    public function saveTanxCreativeSsp($creative, $isUpdate=false) {
        $sspCreative['creative_id'] = $creative['id']; 
        $sspCreative['ad_network_id'] = 2;

        //唯一键
        $uniqueKey = $sspCreative;
        $sspCreative['category_id'] = $creative['category_id']; 
        $sspCreative['form'] = $creative['form'];
        if ($sspCreative['form'] == 0) {
            $sspCreative['creative_code'] = $this->getTanxCreativeCode($creative);
        } else {
            $sspCreative['creative_code'] = '';
        }

        $isExist = \app\models\CreativeSsp::find()->where($uniqueKey)->one();
        $sspCreative['status'] = 0;
        //若已经上传 
        if ($isUpdate && $isExist) {
            // 已上传和待更新的状态设置为待更新
            if (in_array($isExist['status'], [1, -2])) {
                $sspCreative['status'] = -2;
            }
        }
        $save = $this->saveOn('CreativeSsp', $uniqueKey, $sspCreative);
        return $save;
    }

    /**
     * 替换广告位Tanx
     */
    public function getTanxCreativeCode($creative) {
        $template = $this->getOne('CreativeTemplate', ['name' => 'Tanx']);
        $code = $template['code']; 
        $macros = $this->getMacroReplacement();
        foreach ($macros as $macro => $attr) {
            if ($attr && isset($creative[$attr])) {
                $value = $creative[$attr];
                $code = str_replace($macro, $value, $code);
            }
        }
        $code = str_replace('{!dsp_cdn_url}', $macros['{!dsp_cdn_url}'], $code);
        return $code;
    }  

    public function getTanxAds() {
        $tanxAds = $this->getAll('AdvertiserMap', ['ad_network_id' => 2]);
        $tanxAds = $this->getField($tanxAds, ['name', 'advertiser_id'], 'advertiser_id');
        $tanxAds = $this->fieldsMap(['id' => 'advertiser_id', 'text' => 'name'], $tanxAds);
        $tanxAds = json_encode(['data' => $tanxAds], JSON_UNESCAPED_UNICODE);
        return $tanxAds;
    } 

    public function getTanxAdName($advertiserId) {
        if ($advertiserId) {
            $tanxAd = $this->getOne('AdvertiserMap', ['ad_network_id' => 2, 'advertiser_id' => $advertiserId]);
            return $tanxAd['name'];
        }
        return '';
    }

    public function saveCustomCreative($post)
    {
        $cateId = $this->getCreativeCategoryId($post['parent_category'], $post['category']);
        $post['category_id'] = $cateId;
        $post['is_custom'] = 1;
        $post['format_id'] = '1';
        $post['template_id'] = 3;
        $post['type'] == 0 && $post['form'] = 0;
        $post['type'] == 5 && $post['form'] = 2;
        $post['adomain_list'] = trim($post['adomain_list']);
        if(empty($post['id'])) {
            $post['advertiser_id'] = $this->S('advertiser_id');
        }
        if($this->I('solution_id')) {
            $post['advertiser_id'] = $this->getSolutionAdvertiser($this->I('solution_id'));
        }
        return $this->trySaveCreative($post);
    }

    public function saveNewCreative($attributes, $form='', $type='')
    {
        $_POST['name'] = $this->dropBlank($_POST['name']);
        if($form != 'cpe_video') {
            $cateId = $this->getCreativeCategoryId($attributes['parent_category'], $attributes['category']);
            $attributes['category_id'] = $cateId;
        }
        
        $materialIds = [];
        if (isset($attributes['upload_material']) && $attributes['upload_material']) $materialIds = $attributes['upload_material'];
        if (!is_array($materialIds)) {
            $materialIds = [$materialIds];
        }
        $attributes['form'] = 0;
        if ($form == 'video') {
            $attributes['form'] = 1;
            $type=='overlay' && $attributes['type'] = 2;
        } else if ($form == 'mobile') {
            $attributes['form'] = 2;
            $type=='web' && $attributes['type'] = 5;
            $type=='app' && $attributes['type'] = 6;
            if($type=='app'){
                if(isset($attributes['feeds_sub_type'])){
                    $attributes['subadtype'] = $attributes['feeds_sub_type'];
                }
            }
        } else if ($form == 'mobileVideo') {
            $attributes['form'] = 3;
        }else if($form == 'cpe_banner'){
            if(!$attributes['id']){
                $attributes['status'] = 6;
            }
            $attributes['form'] = 4;  
        }else if($form == 'cpe_video'){
            $attributes['form'] = 4;
            $attributes['status'] = 1;
        }
        if (isset($attributes['visible_urls'])) {
            $visibleUrls = $attributes['visible_urls'];
            !is_array($visibleUrls) && $visibleUrls = [];
            $attributes['visible_urls'] = implode('###vamaker-seperator###', $visibleUrls);
        } else {
            $attributes['visible_urls'] = '';
        }
        unset($_POST['visible_urls']);
        if ($form == 'cpe_video') {
            if ($attributes['material_source'] == 0) {
                $this->getCpeUploadMaterialInfo($attributes, $materialIds);
            } else {
                $this->getCpeCustomMaterialInfo($attributes, $form, $type);
            }
        } else {
            if($attributes['material_source'] == 0) {
                unset($_POST['width']);
                unset($_POST['height']);
                unset($_POST['duration']);
                $this->getUploadMaterialInfo($attributes, $materialIds);
            } else {
                $this->getCustomMaterialInfo($attributes, $form, $type);
            }
            if (empty($attributes['id'])) {
                $attributes['advertiser_id'] = $this->S('advertiser_id');
            }
            if($this->I('solution_id')){
                $attributes['advertiser_id'] = $this->getSolutionAdvertiser($this->I('solution_id'));
            }
            if ($form != 'cpe_banner') {
                $attributes['landing_page'] = trim($attributes['landing_page']);
                $_POST['landing_page'] = trim($_POST['landing_page']);
                if(empty($attributes['id'])) {
                    $attributes['advertiser_id'] = $this->S('advertiser_id');
                }
                if($this->I('solution_id')) {
                    $attributes['advertiser_id'] = $this->getSolutionAdvertiser($this->I('solution_id'));
                }
                $adomain = $attributes['landing_page'];
                if (isset($attributes['adomain'])) {
                    $attributes['adomain'] && $adomain = $attributes['adomain'];
                    $attributes['adomain'] && $attributes['adomain_full'] = $attributes['adomain'];
                    $attributes['adomain_list'] = $this->getAdomain($adomain);
                }
                if (isset($attributes['adomain_list']) && !$attributes['adomain_list']) {
                    $attributes['adomain_list'] = $this->getAdomain($adomain);
                    unset($_POST['adomain_list']);
                }
                $implodeAttributes = ['click_monitor_url', 'show_monitor_url'];
                foreach ($implodeAttributes as $att) {
                    if (isset($attributes[$att]) 
                        && is_array($attributes[$att]))
                    {
                        $attributes[$att] = (string) implode(';;;', $attributes[$att]);
                        if (isset($_POST[$att])) unset($_POST[$att]);
                    }
                }
            }
            if (isset($attributes['title']) || isset($attributes['pic_url'])) {
                $attributes['ad_type'] = 3;
            }
        }
        if (in_array($attributes['form'], [1,3])) {
            $cdn = $attributes['file_url'];
            $cdn = trim($cdn, 'https:');
            $cdn = trim($cdn, 'http:');
            $cdn = 'http:'.$cdn;
            $attributes['file_url'] = $cdn;
        }
        return $this->trySaveCreative($attributes);
    }

    public function trySaveCreative($attributes)
    {
        $isUpdate = false;
        if (isset($attributes['id'])) {
            $isUpdate = true;
        }
        if (isset($attributes['type']) && $attributes['type'] == 6) {
            if(isset($attributes['material_source']) && $attributes['material_source'] == 0){
                $protocal = '';
                if ($attributes['protocal'] == 1) $protocal = 'http:';
                if ($attributes['protocal'] == 2) $protocal = 'https:';
                $url = $attributes['file_url'];
                $url = trim($url, 'https:');
                $url = trim($url, 'http:');
                $attributes['file_url'] = $protocal.$url;
            }
        }
        $creative = $this->save('Creative', $attributes);
        if (is_array($creative)) {
            if ($creative['status'] != 6) {
                if ($this->I('solution_id')) {
                    $this->saveNewSolutionCreativeMap($this->I('solution_id'), $creative['id']);
                    $solution = $this->M('Solution', $this->I('solution_id'));
                    $solutionService = new SolutionService();
                    $status = $solution['status'];
                    if ($status == 7) {
                        $solutionService->updateSolutonStatus($this->I('solution_id'),'resume');
                    }
                }
                $this->saveCreativeSsp($creative, $isUpdate);
            }
            
        }
        return $creative;
    }

    public function getSolutionAdvertiser($solutionId){
        $solution = $this->M('solution',$solutionId);
        return $solution['advertiser_id'];
    }
    
    public function getUploadMaterialInfo(&$attributes, $materialIds) {
        $attributes['material_id'] = '';
        $attributes['file_url'] = '';
        $attributes['ext'] = '';
        $attributes['format_id'] = '';
        $attributes['size'] = '';
        $attributes['width'] = '';
        $attributes['height'] = '';
        $attributes['size_list'] = '';
        if ($materialIds) {
            foreach ($materialIds as $materialId) {
                $material = $this->M('Material', (int)$materialId);
                $attributes['material_id'] .= ','.$materialId;
                $attributes['file_url'] .= ','.\Yii::$app->params['cdn'].$material['name'];
                $attributes['ext'] .= ','.strtolower($material['ext']);
                $attributes['size'] .= ','.$material['size'];
                $attributes['width'] .= ','.$material['width'];
                $attributes['height'] .= ','.$material['height'];
                $attributes['size_list'] .= ','.$material['width'].'*'.$material['height'];
            }
            array_walk($attributes, create_function('&$v, $k', 'is_string($v) && $v=trim($v, ",");'));
            $attributes['format_id'] = (string) $this->getMaterialFormat($material['ext']);
            $attributes['duration'] = $material['duration'];
        } else {
            $attributes['format_id'] = (string)$this->getMaterialFormat('');
            $attributes['width'] = '0';
            $attributes['height'] = '0';
        }
        $attributes['width'] = (int) $attributes['width'];
        $attributes['height'] = (int) $attributes['height'];
    }

    public function getCustomMaterialInfo(&$attributes, $form, $type) {
        $model = 'Adspace';
        $form == 'video' && $model = 'VideoAdspace';
        $form == 'mobile' && $model = 'MobileAdspace';
        $form == 'mobileVideo' && $model = 'MobileVideoAdspace';
        if (!is_array($attributes['width'])) {
            $check = $this->auditCustomMaterialSize($attributes['width'], $attributes['height'], $model, $type);
        } else {
            $check = true;
            $datas = array_combine($attributes['width'], $attributes['height']);
            foreach ($datas as $width => $height) {
                $check = $this->auditCustomMaterialSize($width, $height, $model, $type);
                if (!$check) break;
            }
        }
        if (!$check) $this->NG($this->t('creative', 'Material size not correct!'));
        
        $attributes['size'] = '';
        $attributes['material_id'] = '';
        if (is_array($attributes['width']) && $attributes['width']) {
            $ext = strtolower($attributes['material_type'][0]);
            $attributes['file_url'] = implode(',', $attributes['custom_url']);
            $attributes['ext'] = strtolower(implode(',', $attributes['material_type']));
            // $attributes['width'] = implode(',', $attributes['width']);
            // $attributes['height'] = implode(',', $attributes['height']);
            // !$attributes['width'] && $ext = '';
            // !$attributes['width'] && $attributes['width'] = '0';
            // !$attributes['height'] && $attributes['height'] = '0';
            // unset($_POST['width']);
            // unset($_POST['height']);
            
            $sizeList = [];
            foreach ($attributes['width'] as $key => $value) {
                array_push($sizeList, $attributes['width'][$key].'*'.$attributes['height'][$key]);
            }
            $attributes['size_list'] = implode(',', $sizeList);
            $attributes['width'] = (int) $attributes['width'][0];
            $attributes['height'] = (int)  $attributes['height'][0];
            unset($_POST['width']);
            unset($_POST['height']);

        } else {
            $attributes['file_url'] = $attributes['custom_url'];
            $attributes['ext'] = strtolower($attributes['material_type']);
            $ext = $attributes['ext'];
            $attributes['size_list'] = $attributes['width'].'*'.$attributes['height'];
        }
        $attributes['format_id'] = (string)$this->getMaterialFormat($ext);
    }

    public function getCpeUploadMaterialInfo(&$attributes, $materialIds) {
        $att['visible_urls'] = $attributes['visible_urls'];
        $att['cpe_material_source'] = $attributes['material_source'];
        $att['cpe_material_id'] = '';
        $att['cpe_file_url'] = '';
        $att['cpe_ext'] = '';
        $att['cpe_format_id'] = '';
        $att['cpe_duration'] = '';
        $att['cpe_weight'] = '';
        $att['cpe_size_list'] = '';
        $att['id'] = $attributes['id'];
        $att['status'] = $attributes['status'];
        if ($materialIds) {
            foreach ($materialIds as $materialId) {
                $material = $this->M('Material', (int)$materialId);
                $att['cpe_material_id'] .= ','.$materialId;
                $att['cpe_file_url'] .= ','.\Yii::$app->params['cdn'].$material['name'];
                $att['cpe_ext'] .= ','.strtolower($material['ext']);
                $att['cpe_duration'] .= ','.$material['duration'];
                $att['cpe_weight'] .= ','.$material['size'];
                $att['cpe_format_id'] .= ','.(string)$this->getMaterialFormat($material['ext']);
                $att['cpe_size_list'] .= ','.$material['width'].'*'.$material['height'];
            }
            array_walk($att, create_function('&$v, $k', 'is_string($v) && $v=trim($v, ",");'));
        }
        $att['duration'] = max(explode(',',$att['cpe_duration']));
        $attributes['landing_page'] = trim($attributes['landing_page']);             
        $adomain = $attributes['landing_page'];
        if (isset($attributes['adomain'])) {
            $attributes['adomain'] && $adomain = $attributes['adomain'];
            $attributes['adomain'] && $att['adomain_full'] = $attributes['adomain'];
            $att['adomain_list'] = $this->getAdomain($adomain);
        }
        if (isset($attributes['adomain_list']) && !$attributes['adomain_list']) {
            $att['adomain_list'] = $this->getAdomain($adomain);
            unset($_POST['adomain_list']);
        }
        $att['cpe_landing_page'] = $attributes['landing_page'];
        $att['cpe_show_monitor_url'] = implode(';;;',$attributes['show_monitor_url']);
        $att['cpe_click_monitor_url'] = implode(';;;',$attributes['click_monitor_url']);
        unset($_POST['material_source']);
        unset($_POST['landing_page']);
        unset($_POST['duration']);
        unset($_POST['show_monitor_url']);
        unset($_POST['click_monitor_url']);
        $attributes = $att;
    }

    public function getCpeCustomMaterialInfo(&$attributes, $form, $type) {
        $att['cpe_material_source'] = $attributes['material_source'];
        $att['visible_urls'] = $attributes['visible_urls'];
        $att['cpe_weight'] = '';
        $att['cpe_material_id'] = '';
        $att['id'] = $attributes['id'];
        $att['status'] = $attributes['status'];
        if (is_array($attributes['material_size']) && $attributes['material_size']) {
            $att['cpe_file_url'] = implode(',', $attributes['custom_url']);
            $att['cpe_ext'] = strtolower(implode(',', $attributes['material_type']));
            $cpe_format_id_arr = [];
            foreach ($attributes['material_type'] as $key => $value) {
                array_push($cpe_format_id_arr,$this->getMaterialFormat(strtolower($value)));
            }
            $att['cpe_format_id'] = implode(',', $cpe_format_id_arr);
            $att['cpe_duration'] = implode(',', $attributes['duration']);
            $att['cpe_size_list'] = implode(',', $attributes['material_size']);
        }
        $att['duration'] = max(explode(',',$att['cpe_duration']));
        $attributes['landing_page'] = trim($attributes['landing_page']);             
        $adomain = $attributes['landing_page'];
        if (isset($attributes['adomain'])) {
            $attributes['adomain'] && $adomain = $attributes['adomain'];
            $attributes['adomain'] && $att['adomain_full'] = $attributes['adomain'];
            $att['adomain_list'] = $this->getAdomain($adomain);
        }
        if (isset($attributes['adomain_list']) && !$attributes['adomain_list']) {
            $att['adomain_list'] = $this->getAdomain($adomain);
            unset($_POST['adomain_list']);
        }
        $att['cpe_landing_page'] = $attributes['landing_page'];
        $att['cpe_show_monitor_url'] = implode(';',$attributes['show_monitor_url']);
        $att['cpe_click_monitor_url'] = implode(';',$attributes['click_monitor_url']);
        unset($_POST['material_source']);
        unset($_POST['landing_page']);
        unset($_POST['duration']);
        unset($_POST['material_type']);
        unset($_POST['custom_url']);
        unset($_POST['show_monitor_url']);
        unset($_POST['click_monitor_url']);
        $attributes = $att;
    }

    public function auditCustomMaterialSize($width, $height, $model, $type) {
        if ($model == 'VideoAdspace' || $model == 'MobileVideoAdspace') {
            return true;
        }
        $adnetworkId = $this->S('ad_network_id');
        !$adnetworkId && $adnetworkId = 1;
        $sizes = $this->getAvailableCreativeSize($model, $adnetworkId, $this->I('soluton_id'), $type);
        $accept = false; 
        if ($type == 'web') {
            foreach ($sizes as $size) {
                if ($width/$size['width'] == $height/$size['height'] && $width%$size['width']==0 && $height%$size['height']==0) {
                    $accept = true; 
                    break;
                }
            }
        } else if ($type == 'app') {
            foreach ($sizes as $size) {
                if ($width <= $size['width'] && $height <= $size['height']) {
                    $accept = true;
                    break;
                }
            }
        } else {
            foreach ($sizes as $size) {
                if ($size['width'] == $width && $size['height'] == $height) {
                    $accept = true;
                    break;
                }
            }
        }
        return $accept;
    }

    public function getCreativeMaterials($creative) {
        if (!$creative['material_id'])  return [];
        $materialIds = array_combine(explode(',', $creative['material_id']), explode(',', $creative['file_url']));
        $materials = [];
        foreach ($materialIds as $key => $url) {
            $material = $this->M('Material', (int) $key);
            $material['url'] = $url;
            $materials[] = $material;
        }
        return $materials;
    }

    public function getCpeCreativeMaterials($mids) {
        $where = " id in ($mids) ";
        $materials = $this->getAll('Material', $where);
        return $materials;
    }

    public function uploadMobileWebPic() {
        $solutionId = $this->S('solution_id');
        $advertiserId = $this->S('advertiser_id');
        $result = $this->uploadPic($solutionId, $advertiserId, ['jpg','png','gif']);
        if (!is_array($result)) {
            $this->NG($result);
        }
        $adnetworkId = $this->S('ad_network_id');
        //$sizes = $this->getAvailableCreativeSize('MobileAdspace', $adnetworkId, $this->I('solution_id'), 'web');
        //$width = $result['width'];
        //$height = $result['height'];
        //$accept = false; 
        //foreach ($sizes as $size) {
        //    if ($width/$size['width'] == $height/$size['height'] && $width%$size['width']==0 && $height%$size['height']==0) {
        //        $accept = true; 
        //        break;
        //    }
        //}
        //if (!$accept) $this->NG($this->t('creative', 'Material size not correct!'));
        if (is_array($result)) {
            $result = $this->getRef($result, 'MobileAdspace'); if ($result['table']['judgeInfo']  == $this->t('creative', 'unqualified')) {
                $this->NG($this->t('creative', 'Material is not qualified!'));
            }
            $this->OK($this->t('creative', 'Material uploaded!'), 'ok', $result);
        }
        $this->NG($result);
    }

    public function uploadMobileAppPic() {
        $solutionId = $this->S('solution_id');
        $advertiserId = $this->S('advertiser_id');
        $result = $this->uploadPic($solutionId, $advertiserId, ['jpg','png','gif']);
        if (!is_array($result)) {
            $this->NG($result);
        }
        $adnetworkId = $this->S('ad_network_id');
        //$sizes = $this->getAvailableCreativeSize('MobileAdspace', $adnetworkId, $this->I('solution_id'), 'app');
        //$width = $result['width'];
        //$height = $result['height'];
        //$accept = false; 
        //foreach ($sizes as $size) {
        //    if ($width <= $size['width'] && $height <= $size['height']) {
        //        $accept = true; 
        //        break;
        //    }
        //}
        //if (!$accept) $this->NG($this->t('creative', 'Material size not correct!'));
        if (is_array($result)) {
            $result = $this->getRef($result, 'MobileAdspace');
            if ($result['table']['judgeInfo']  == $this->t('creative', 'unqualified')) {
                $this->NG($this->t('creative', 'Material is not qualified!'));
            }
            $this->OK($this->t('creative', 'Material uploaded!'), 'ok', $result);
        }
        $this->NG($result);
    }

    public function uploadBannerPic() {
        $solutionId = $this->S('solution_id');
        $advertiserId = $this->S('advertiser_id');
        $result = $this->uploadPic($solutionId, $advertiserId, ['jpg','png','gif','swf']);
        if (is_array($result)) {
            $result = $this->getRef($result, 'Adspace');
            if ($result['table']['judgeInfo']  == $this->t('creative', 'unqualified')) {
                $this->NG($this->t('creative', 'Material not qualified!'));
            }
            $this->OK($this->t('creative', 'Update material successfully!'), 'ok', $result);
        }
        $this->NG($result);
    }

    public function uploadVideoPic($model) {
        $solutionId = $this->S('solution_id');
        $advertiserId = $this->S('advertiser_id');
        $result = $this->uploadVideo($solutionId, $advertiserId);
        if (is_array($result)) {
            $result = $this->getRef($result, $model);
            if ($result['table']['judgeInfo']  == $this->t('creative', 'unqualified')) {
                $this->NG($this->t('creative', 'Material not qualified!'));
            }
            $this->OK($this->t('creative', 'Update material successfully!'), 'ok', $result);
        }
        $this->NG($result);
    }

    public function getVideoData($material, $creative) {
        switch ($creative['format_id']) {
              case 1:
                $type = 'jpg';
                break;
                case 2:
                $type = 'png';
                break;
                case 3:
                $type = 'swf';
                break;
            case 5:
                $type = 'flv';
                 break;
            case 6:
                $type = 'mp4';
                break;
            default:
                $type = 'flv';
                break;
        }
        $videoData['materialId'] = $creative['material_id'];
        $videoData['info'] = ['width' => $creative['width'], 
                      'height' => $creative['height'],
                      'type' => $type,
                      'address' => $creative['file_url']];
        return $this->toJson($videoData);
    }

    public function getCpeCreativePreview($creativeId){
        $creative = $this->getOne('Creative', ['id' =>  $creativeId]);
        $creativeList = [];
        $bannerCretive['id'] = 1;
        $bannerCretive['type'] = 'banner';
        $bannerCretive['url'] = $creative['file_url'];
        $bannerCretive['format'] = $creative['ext'];
        array_push($creativeList, $bannerCretive);
        $cpeFileUrl = explode(',',$creative['cpe_file_url']);
        $cpeFormat = explode(',', $creative['cpe_ext']);
        foreach ($cpeFileUrl as $key => $value) {
            $cpeCreative['id'] = $key+1;
            $cpeCreative['type'] = 'video';
            $cpeCreative['url'] = $value;
            $cpeCreative['format'] = $cpeFormat[$key];
            array_push($creativeList,$cpeCreative);
        }
        $res = [
            'editable' => true,
            'list' => $creativeList
        ];
        return $res;
    }
}//end of creative service declaration
